

function erdApplication() {
    var dragIndex;
    var dragging;
    var mouseX;
    var mouseY;
    var dragHoldX;
    var dragHoldY;
    var timer;
    var targetX;
    var targetY;
    var easeAmount;

    // hook up the canvas drawing context
    var c = document.getElementById("myCanvas");
    var context = c.getContext("2d");

    // call the init method
    init();


    /**
    @function {void} init - sets up the app
    */
    function init() {
        easeAmount = 0.45;

        myCanvas.addEventListener("mousedown", mouseDownListener, false);
        loadBaseTables();

        drawScreen();
    } // init() - end

    /**
    @function {void} loadBaseTables - this loads up the base tables of our schema
    */
    function loadBaseTables() {
        erdTableCount++;
        var temp = new erdTable("Contact", 275, 25);
        temp.loadColumns();
        erdTables.push(temp);

        erdTableCount++;
        temp = new erdTable("identifier", 20, 240);
        temp.loadColumns();
        erdTables.push(temp);

        erdTableCount++;
        temp = new erdTable("Contractrole", 550, 50);
        temp.loadColumns();
        erdTables.push(temp);

        erdTableCount++;
        temp = new erdTable("Contractcomponent", 800, 30);
        temp.loadColumns();
        erdTables.push(temp);

        erdTableCount++;
        temp = new erdTable("Contract", 800, 370);
        temp.loadColumns();
        erdTables.push(temp);

        // set up the connection objects (this is just a test connection)
        //var col1 = erdTables[0].cols[0]; // 0
        //var col2 = erdTables[1].cols[2]; // 2
        // i really need to automate this process...
        erdConns.push(new erdConnection("CtoI", erdTables[0].cols[0], "l", erdTables[1].cols[2], "r"));
        erdConns.push(new erdConnection("CtoR", erdTables[0].cols[0], "r", erdTables[2].cols[1], "l"));
        erdConns.push(new erdConnection("RtoC", erdTables[2].cols[2], "r", erdTables[3].cols[0], "l"));
        erdConns.push(new erdConnection("PtoC", erdTables[3].cols[3], "l", erdTables[4].cols[0], "l"));
    }


    /**
    @function {void} mouseDownListener - handle mouse down
    @param {Event} evt - the event being listened for
    */
    function mouseDownListener(evt) {
        //getting mouse position correctly
        var bRect = myCanvas.getBoundingClientRect();
        mouseX = (evt.clientX - bRect.left) * (myCanvas.width / bRect.width);
        mouseY = (evt.clientY - bRect.top) * (myCanvas.height / bRect.height);

        for (i = 0; i < erdTableCount; i++) {
            if (erdTables[i].hitTest(mouseX, mouseY)) {
                dragging = true;
                //the following variable will be reset if this loop repeats with another successful hit:
                dragIndex = i;
            }
        }

        if (dragging) {
            window.addEventListener("mousemove", mouseMoveListener, false);

            //place currently dragged shape on top
            erdTables.push(erdTables.splice(dragIndex, 1)[0]);

            //shapeto drag is now last one in array
            dragHoldX = mouseX - erdTables[erdTableCount - 1].x; //erd.x;
            dragHoldY = mouseY - erdTables[erdTableCount - 1].y; //erd.y;

            //The "target" position is where the object should be if it were to move there instantaneously. But we will
            //set up the code so that this target position is approached gradually, producing a smooth motion.
            targetX = mouseX - dragHoldX;
            targetY = mouseY - dragHoldY;

            //start timer
            timer = setInterval(onTimerTick, 1000 / 30);
        }

        myCanvas.removeEventListener("mousedown", mouseDownListener, false);
        window.addEventListener("mouseup", mouseUpListener, false);

        //code below prevents the mouse down from having an effect on the main browser window:
        if (evt.preventDefault) {
            evt.preventDefault();
        } //standard
        else if (evt.returnValue) {
            evt.returnValue = false;
        } //older IE

        return false;

    } // mouseDownListener() - end


    /**
    @function {void} mouseUpListener - handle the mouse up
    @param {Event} evt - the event being listened for
    */
    function mouseUpListener(evt) {
        myCanvas.addEventListener("mousedown", mouseDownListener, false);
        window.removeEventListener("mouseup", mouseUpListener, false);
        if (dragging) {
            dragging = false;
            window.removeEventListener("mousemove", mouseMoveListener, false);
        }

    } // mouseUpListener() - end


    /**
    @function {void} mouseMoveListener - handle the mouse move
    @param {Event} evt - the event being listened for
    */
    function mouseMoveListener(evt) {
        var posX;
        var posY;
        var shapeRad = erdTables[erdTableCount - 1].radius; //erd.radius;
        var minX = shapeRad;
        var maxX = myCanvas.width - shapeRad;
        var minY = shapeRad;
        var maxY = myCanvas.height - shapeRad;

        //getting mouse position correctly 
        var bRect = myCanvas.getBoundingClientRect();
        mouseX = (evt.clientX - bRect.left) * (myCanvas.width / bRect.width);
        mouseY = (evt.clientY - bRect.top) * (myCanvas.height / bRect.height);

        //clamp x and y positions to prevent object from dragging outside of canvas
        posX = mouseX - dragHoldX;
        posX = (posX < minX) ? minX : ((posX > maxX) ? maxX : posX);
        posY = mouseY - dragHoldY;
        posY = (posY < minY) ? minY : ((posY > maxY) ? maxY : posY);

        targetX = posX;
        targetY = posY;

    } // mouseMoveListener() - end


    /**
    @function {void} onTimerTick - this runs while the mouse is down drawing the screen to show the movement
    */
    function onTimerTick() {
        //because of reordering, the dragging shape is the last one in the array.
        erdTables[erdTableCount - 1].updatePosition(erdTables[erdTableCount - 1].x + easeAmount * (targetX - erdTables[erdTableCount - 1].x),
                                                    erdTables[erdTableCount - 1].y + easeAmount * (targetY - erdTables[erdTableCount - 1].y));

        //stop the timer when the target position is reached (close enough)
        if ((!dragging) && (Math.abs(erdTables[erdTableCount - 1].x - targetX) < 0.1) &&
			(Math.abs(erdTables[erdTableCount - 1].y - targetY) < 0.1)) {

            erdTables[erdTableCount - 1].updatePosition(targetX, targetY);

            //stop timer:
            clearInterval(timer);
        }

        drawScreen();
    } // onTimerTick() - end


    /**
    @function {void} drawScreen - refreshes the screen
    */
    function drawScreen() {
        // refresh the canvas
        context.fillStyle = "#ffffff";
        context.fillRect(0, 0, myCanvas.width, myCanvas.height);
        // draw all the tables
        drawTables();
    } // drawScreen() - end


    /**
    @function {void} drawTables - draws the tables on the canvas
    */
    function drawTables() {
        for (i = 0; i < erdTableCount; i++) {
            //the drawing of the shape is handled by a function inside the external class.
            //we must pass as an argument the context to which we are drawing the shape.
            erdTables[i].drawToContext(context);
        }

        // try and draw the connections
        for (i = 0; i < erdConns.length; i++) {
            erdConns[i].drawToContext(context);
        }

    } // drawTables() - end

}

